#pragma once
#include <highgui.h>

namespace Common
{
	CvMat*  cvCalculateDerivativeMap(CvMat* m, const IplImage* graySource)
	{		
		unsigned char *d = (unsigned char *)graySource->imageData;		
		unsigned char *dst = m->data.ptr;

		for (int y = 0; y < graySource->height - 1; y++)
		{
			unsigned char *p = d;
			for (int x = 0; x < graySource->width - 1; x++, p++)
			{
				int center = *p;
				int right = *(p + 1);
				int down = *(p + graySource->widthStep);
				int res = ((right - center) > 0)*2 + ((down - center) > 0);
				
				*dst = res;
				dst++;
			}
			d += graySource->widthStep;
		}		
		return m;
	}

	CvMat*  cvCalculateDerivativeMap(const IplImage* graySource)
	{		
		CvMat* m = cvCreateMat(graySource->height - 1, graySource->width - 1, CV_8U);		
		return cvCalculateDerivativeMap(m, graySource);
	}

	void unitTest()
	{
		IplImage* img = cvCreateImage(cvSize(3,3), 8,1);
		img->imageData[0] = 1;
		img->imageData[1] = 240;
		img->imageData[2] = 3;
		img->imageData[3] = -1;  //fetching

		img->imageData[4] = 4;
		img->imageData[5] = 4;
		img->imageData[6] = 5;
		img->imageData[7] = -2;  //fetching

		img->imageData[8] = 1;
		img->imageData[9] = 1;
		img->imageData[10] = 1;
		img->imageData[11] = -3;  //fetching

		CvMat* res = cvCalculateDerivativeMap(img);
		unsigned char *data = res->data.ptr;

		for (int y = 0; y < res->rows; y++)
		{
			for (int x = 0; x < res->cols; x++, data++)
			{
				int d = *data;
				printf("%u ", d);
			}
			printf("\r\n");
		}

		cvReleaseMat(&res);		

	}


	void intTest2()
	{
		int ww = 32;
		int hh = 32;

		IplImage* img = cvLoadImage("images\\p2.JPG");

		IplImage* gray = cvCreateImage(cvGetSize(img), 8, 1);
		cvCvtColor(img, gray, CV_BGR2GRAY);

		IplImage* p = cvCreateImage(cvSize(ww,hh), 8, 1);
		int x = 260;
		int y = 290;

		unsigned char* src = ((unsigned char*)gray->imageData) + y * gray->widthStep + x;
		unsigned char* dst = (unsigned char*)(p->imageData);
		for (int i = 0; i < hh; i++, dst += p->widthStep, src += gray->widthStep)
			memcpy(dst,src, ww);

		cvRectangle(img, cvPoint(x,y), cvPoint(x + ww, y + hh), CV_RGB(255,255,255));
		cvSmooth(gray,gray);

		cvShowImage("full", img);
		cvShowImage("cut", p);

		cvWaitKey(0);

		CvMat * d = cvCalculateDerivativeMap(gray);
		CvMat * dp = cvCalculateDerivativeMap(p);

		int biggetSum = 0;
		int foundX, foundY;
		for (int y = 0; y < d->height - dp->height; y++)
		{
			for (int x = 0; x < d->width - dp->width; x++)
			{
				unsigned char* frame = ((unsigned char*)d->data.ptr) + y * d->width + x;
				unsigned char* cut = (unsigned char*)dp->data.ptr;
				int sum = 0;

				for (int j = 0; j < dp->height; j++)
				{
					for (int i = 0; i < dp->width; i++)
					{
						sum += cut[i] == frame[i];
					}
					cut += dp->width;
					frame += d->width;
				}

				if (biggetSum < sum)
				{
					foundX = x;
					foundY = y;
					biggetSum = sum;
				}
			}
		}
	
		printf("biggetSum: %i",biggetSum);
		cvRectangle(img, cvPoint(foundX, foundY), cvPoint(foundX + ww, foundY + hh), CV_RGB(0,255,0));
		cvShowImage("full", img);
		cvWaitKey(0);
			
		cvReleaseImage(&img);
		cvReleaseImage(&gray);
		cvReleaseImage(&p);
	}
};